package de.wwu.moneyrec;

import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ImageLoaderDB {
	
	public static final String MONEY_DIR = "C:/Users/monnti/Dropbox/Geldscheinerkenung/gute bilder/";	
	public static final String MONEY_DIR_DB = MONEY_DIR + "imageDB.imgDB";
	public static final String MONEY_DIR_DB_ANDROID = MONEY_DIR + "imageDBAndroid.imgDB";
	
	public static final String MONDEY_5 = "5 blitz/";
	public static final String MONDEY_10 = "10 blitz/";
	public static final String MONDEY_20 = "20 blitz/";
	public static final String MONDEY_50 = "50 blitz/";
	public static final String MONDEY_100 = "100 blitz/";
	public static final String MONDEY_200 = "200 blitz/";
	public static final String MONDEY_500 = "500 blitz/";
	public static final String UNKNOWN_MONEY = "unknown/";
	
	public LinkedList<Color> fives = new LinkedList<Color>();
	public LinkedList<Color> tens = new LinkedList<Color>();
	public LinkedList<Color> twentys = new LinkedList<Color>();
	public LinkedList<Color> fiftys = new LinkedList<Color>();
	public LinkedList<Color> one_hundreds = new LinkedList<Color>();
	public LinkedList<Color> two_hundreds = new LinkedList<Color>();
	public LinkedList<Color> five_hundreds = new LinkedList<Color>();
	
	public int numberOFReadInMOney= 0;
	
	private int sizeOfFiles;
	private int finishedIMG = 0;
	private int maxThreadNumber = 8;
	
	public void loadImages(){
		ExecutorService executor = Executors.newFixedThreadPool(maxThreadNumber);
		
		long startTime = System.currentTimeMillis();
//		loadDBFile();
		loadDbFromImages(executor);
		loadDBImages((MONEY_DIR + UNKNOWN_MONEY), null, executor);
		
		executor.shutdown();
		while (!executor.isTerminated()) {
		}
		System.out.println("geladene scheine: 5: " + fiftys.size() + " 10: " + tens.size() + " 20: " + twentys.size() + " 50: " + fiftys.size() + 
				" 100: " + one_hundreds.size() + " 200: " + two_hundreds.size() +" 500: " + five_hundreds.size());
		float diff = System.currentTimeMillis() - startTime;
		float time = diff / 1000f;
		
		System.out.println("Rechenzeit: " + time);
		
//		saveDBFile();
		saveDBFileAndroid();
	}
	
	private void loadDBFile(){
		LinkedList<LinkedList<Color>> colorDB = new LinkedList<LinkedList<Color>>();
		File direct = new File(MONEY_DIR_DB);
		
		
		try {
			FileInputStream fOut = new FileInputStream(direct);
			ObjectInputStream out = new ObjectInputStream(fOut);
			
			colorDB =(LinkedList<LinkedList<Color>>) out.readObject();
			
			fives = colorDB.get(0);
			tens = colorDB.get(1);
			twentys = colorDB.get(2);
			fiftys = colorDB.get(3);
			one_hundreds = colorDB.get(4);
			two_hundreds = colorDB.get(5);
			five_hundreds = colorDB.get(6);
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	
	private void saveDBFile(){
		try {
			LinkedList<LinkedList<Color>> colorDB = new LinkedList<LinkedList<Color>>();
			colorDB.add(fives);
			colorDB.add(tens);
			colorDB.add(twentys);
			colorDB.add(fiftys);
			colorDB.add(one_hundreds);
			colorDB.add(two_hundreds);
			colorDB.add(five_hundreds);
			
			File direct = new File(MONEY_DIR_DB);
			FileOutputStream fOut = new FileOutputStream(direct);
			ObjectOutputStream out = new ObjectOutputStream(fOut);
			
			out.writeObject(colorDB);
			
			fOut.flush();
			out.flush();
			fOut.close();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void saveDBFileAndroid(){
		try {
			LinkedList<LinkedList<Color>> colorDB = new LinkedList<LinkedList<Color>>();
			colorDB.add(fives);
			colorDB.add(tens);
			colorDB.add(twentys);
			colorDB.add(fiftys);
			colorDB.add(one_hundreds);
			colorDB.add(two_hundreds);
			colorDB.add(five_hundreds);
			
			LinkedList<LinkedList<Money>> colorDBM = new LinkedList<LinkedList<Money>>();
			for (LinkedList<Color> linkedList : colorDB) {
				LinkedList<Money> moneyList = new LinkedList<Money>();
				colorDBM.add(moneyList);
				for (Color color : linkedList) {
					int r = color.getRed();
					int g = color.getGreen();
					int b = color.getBlue();
					moneyList.add(new Money(r, g, b));
				}
			}
			
			
			
			File direct = new File(MONEY_DIR_DB_ANDROID);
			FileOutputStream fOut = new FileOutputStream(direct);
			ObjectOutputStream out = new ObjectOutputStream(fOut);
			
			out.writeObject(colorDBM);
			
			fOut.flush();
			out.flush();
			fOut.close();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void loadDbFromImages(ExecutorService executor){
		loadDBImages((MONEY_DIR + MONDEY_5), fives, executor);
		loadDBImages((MONEY_DIR + MONDEY_10), tens, executor);
		loadDBImages((MONEY_DIR + MONDEY_20), twentys, executor);
		loadDBImages((MONEY_DIR + MONDEY_50), fiftys, executor);
		loadDBImages((MONEY_DIR + MONDEY_100), one_hundreds, executor);
		loadDBImages((MONEY_DIR + MONDEY_200), two_hundreds, executor);
		loadDBImages((MONEY_DIR + MONDEY_500), five_hundreds, executor);
	}
	
	private void loadDBImages(String dirPath, LinkedList<Color> moneyTypes, ExecutorService executor){
		/**
		 * startet die threads zum lesen der files
		 */
		File dir = new File(dirPath);
		String[] fileNames = dir.list();
		sizeOfFiles =  fileNames.length;
		
		for (String string : fileNames) {
			String fileName = dirPath + string;
			
			Thread thread = new ImageOperationDBClusterThread(fileName, this, moneyTypes);
			executor.execute(thread);
		}
	}
	
	public void finishedOperation(){
		numberOFReadInMOney++;
		System.out.println("numberOfReadInMoney: " + numberOFReadInMOney);
	}
}
